//
//  NSMAssetsManager.m
//  NSMKit
//
//  Created by nsm on 2019/2/27.
//  Copyright © 2019 nani. All rights reserved.
//

#import "NSMAssetsManager.h"
//#import "NSMKit.h"
//#import <YYKit.h>

@interface NSMAssetsManager ()
@property (nonatomic, strong) PHCachingImageManager *cachingImageManager;
@end

@implementation NSMAssetsManager

+ (instancetype)sharedInstance {
    static NSMAssetsManager *instance = nil;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        instance = [[super allocWithZone:NULL] init];
    });
    return instance;
}

+ (instancetype)allocWithZone:(struct _NSZone *)zone {
    return [self sharedInstance];
}

+ (NSMAssetAuthorizationStatus)authorizationStatus {
    NSMAssetAuthorizationStatus status = NSMAssetAuthorizationStatusNotAuthorized;
    switch (PHPhotoLibrary.authorizationStatus) {
        case PHAuthorizationStatusNotDetermined:
            status = NSMAssetAuthorizationStatusNotDetermined;
            break;
        case PHAuthorizationStatusAuthorized:
            status = NSMAssetAuthorizationStatusAuthorized;
            break;
        default:
            break;
    }
    return status;
}

+ (void)requestAuthorization:(void (^)(NSMAssetAuthorizationStatus))handler {
    [PHPhotoLibrary requestAuthorization:^(PHAuthorizationStatus PHStatus) {
        NSMAssetAuthorizationStatus status = NSMAssetAuthorizationStatusNotAuthorized;
        switch (PHStatus) {
            case PHAuthorizationStatusNotDetermined:
                status = NSMAssetAuthorizationStatusNotDetermined;
                break;
            case PHAuthorizationStatusAuthorized:
                status = NSMAssetAuthorizationStatusAuthorized;
                break;
            default:
                break;
        }
        dispatch_async(dispatch_get_main_queue(), ^{
            !handler?:handler(status);
        });
    }];
}

#pragma mark - setter/getter
- (PHCachingImageManager *)cachingImageManager {
    if (!_cachingImageManager) {
        _cachingImageManager = PHCachingImageManager.new;
    }
    return _cachingImageManager;
}

/*
 enum PHAssetCollectionType : int {
 case Album //从 iTunes 同步来的相册，以及用户在 Photos 中自己建立的相册
 case SmartAlbum //经由相机得来的相册
 case Moment //Photos 为我们自动生成的时间分组的相册
 }
 
 enum PHAssetCollectionSubtype : Int {
 case AlbumRegular //用户在 Photos 中创建的相册，也就是我所谓的逻辑相册
 case AlbumSyncedEvent //使用 iTunes 从 Photos 照片库或者 iPhoto 照片库同步过来的事件。然而，在iTunes 12 以及iOS 9.0 beta4上，选用该类型没法获取同步的事件相册，而必须使用AlbumSyncedAlbum。
 case AlbumSyncedFaces //使用 iTunes 从 Photos 照片库或者 iPhoto 照片库同步的人物相册。
 case AlbumSyncedAlbum //做了 AlbumSyncedEvent 应该做的事
 case AlbumImported //从相机或是外部存储导入的相册，完全没有这方面的使用经验，没法验证。
 case AlbumMyPhotoStream //用户的 iCloud 照片流
 case AlbumCloudShared //用户使用 iCloud 共享的相册
 case SmartAlbumGeneric //文档解释为非特殊类型的相册，主要包括从 iPhoto 同步过来的相册。由于本人的 iPhoto 已被 Photos 替代，无法验证。不过，在我的 iPad mini 上是无法获取的，而下面类型的相册，尽管没有包含照片或视频，但能够获取到。
 case SmartAlbumPanoramas //相机拍摄的全景照片
 case SmartAlbumVideos //相机拍摄的视频
 case SmartAlbumFavorites //收藏文件夹
 case SmartAlbumTimelapses //延时视频文件夹，同时也会出现在视频文件夹中
 case SmartAlbumAllHidden //包含隐藏照片或视频的文件夹
 case SmartAlbumRecentlyAdded //相机近期拍摄的照片或视频
 case SmartAlbumBursts //连拍模式拍摄的照片，在 iPad mini 上按住快门不放就可以了，但是照片依然没有存放在这个文件夹下，而是在相机相册里。
 case SmartAlbumSlomoVideos //Slomo 是 slow motion 的缩写，高速摄影慢动作解析，在该模式下，iOS 设备以120帧拍摄。不过我的 iPad mini 不支持，没法验证。
 case SmartAlbumUserLibrary //这个命名最神奇了，就是相机相册，所有相机拍摄的照片或视频都会出现在该相册中，而且使用其他应用保存的照片也会出现在这里。
 case Any //包含所有类型
 }
 */

#pragma mark - public
- (NSArray<NSMAssetsGroup *> *)fecthAssetGroupsWithSourceType:(NSMAssetSourceType)sourceType {
    // 系统相册(所有相机拍摄的照片或视频以及使用其他应用保存的照片)
    PHFetchResult *smartAlbum  = [PHAssetCollection fetchAssetCollectionsWithType:PHAssetCollectionTypeSmartAlbum subtype:PHAssetCollectionSubtypeSmartAlbumUserLibrary options:nil];
    // 自定义相册(自己新增或者其他应用创建)
    PHFetchResult *userAlbum = [PHCollectionList fetchTopLevelUserCollectionsWithOptions:nil];
    NSArray *albums = @[smartAlbum, userAlbum];
    
    PHFetchOptions *fetchOptions = [self fetchOptionsWithSourceType:sourceType];
    NSMutableArray<NSMAssetsGroup *> *results = @[].mutableCopy;
    for (PHFetchResult *fetchResult in albums) {
        for (PHCollection *collection in fetchResult) {
            // 有可能是PHCollectionList类的的对象,过滤掉
            if (![collection isKindOfClass:PHAssetCollection.class]) continue;
            
            PHAssetCollection *assetCollection = (PHAssetCollection *)collection;
            // 过滤空相册
            NSMAssetsGroup *assetGroup = [NSMAssetsGroup groupWithAssetCollection:assetCollection options:fetchOptions];
            if (assetGroup.numberOfAssets > 0) {
                [results addObject:assetGroup];
            }
        }
    }
    return results;
}

- (PHImageRequestID)fecthThumbnailImageForAsset:(PHAsset *)asset size:(CGSize)size completion:(void (^)(UIImage * _Nullable, NSDictionary * _Nullable))completion {
    PHImageRequestOptions *options = PHImageRequestOptions.new;
    options.resizeMode = PHImageRequestOptionsResizeModeFast;
    CGSize targetSize = CGSizeMake(size.width*kScreenScale, size.height*kScreenScale);
    return [self.cachingImageManager requestImageForAsset:asset targetSize:targetSize contentMode:PHImageContentModeAspectFill options:options resultHandler:^(UIImage * _Nullable result, NSDictionary * _Nullable info) {
        !completion?:completion(result, info);
    }];
}

#pragma mark - private
- (PHFetchOptions *)fetchOptionsWithSourceType:(NSMAssetSourceType)sourceType {
    PHFetchOptions *fetchOptions = PHFetchOptions.new;
    switch (sourceType) {
        case NSMAssetSourceTypePhoto:
            fetchOptions.predicate = [NSPredicate predicateWithFormat:@"mediaType = %i", PHAssetMediaTypeImage];
            break;
        case NSMAssetSourceTypeVideo:
            fetchOptions.predicate = [NSPredicate predicateWithFormat:@"mediaType = %i",PHAssetMediaTypeVideo];
            break;
        case NSMAssetSourceTypeAudio:
            fetchOptions.predicate = [NSPredicate predicateWithFormat:@"mediaType = %i",PHAssetMediaTypeAudio];
            break;
        default:
            break;
    }
    return fetchOptions;
}

@end
